#include "../inc/lcd.h"
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/mman.h>
#include <linux/input.h>

#define TS_PATH "/dev/input/event0"
#define LCD_PATH "/dev/fb0"
#define LCD_WIDTH 800
#define LCD_HEIGHT 480
#define LCD_BPP 4
#define LCD_SIZE ((LCD_HEIGHT) * (LCD_WIDTH) * (LCD_BPP))


int InitTs()
{
	// 打开设备文件
	int fd_ts = open( TS_PATH , O_RDONLY );
	if (fd_ts < 0)
	{
		perror("open event0 error");
		return -1 ;
	}

	return fd_ts ;
}

int getXY( int fd_ts , int * x , int * y )
{
	

	// 读取文件的数据
	struct input_event event ;
	int startX = -1;
	int endX = -1;
	
	while (1)
	{
		int ret_val = read( fd_ts , &event , sizeof(event) );
		if (ret_val < 0)
		{
			perror("读取失败..\n");
			return -1 ;
		}

		if (event.type == EV_ABS )
		{
			if (event.code == ABS_X )
			{
				endX = event.value ;  // 蓝色PCB
				// *x = event.value * 800 / 1024 ;  // 黑色PCB
				if(startX==-1)
				{
					startX = event.value;
				}
				*x = startX-endX;
				
			}
			else if (event.code == ABS_Y )
			{
				*y = event.value ;// 蓝色PCB
				// *y = event.value * 480 / 600 ;// 黑色PCB
			}
		}
		else if ( event.type == EV_KEY && 
					event.code == BTN_TOUCH && 
					event.value == 0 )
		{
			/* 松手后返回 */
			printf("x:%d,startX:%d,endX:%d\n",*x,startX,endX);
			printf("%s:(%d,%d)\n" , __FUNCTION__ , endX , *y );
			
		 	break;
		}
		

		// printf("Time:%d.%d \t Type:%d \t Code:%d \t Value:%d\n",
		// 		event.time.tv_sec , 
		// 		event.time.tv_usec,
		// 		event.type ,
		// 		event.code ,
		// 		event.value
		// 		);
	}
	
	
	return 0;
}


lcdInfo *  InitLCD( void )
{

	lcdInfo * lcd = calloc( 1 , sizeof(lcdInfo) );


	// 打开LCD显示器
	lcd->fd = open( LCD_PATH , O_RDWR );
	if (lcd->fd < 0)
	{
		perror( "open lcd error" );
		goto OpenLcdError;  // 无条件跳转到指定的位置执行
		
	}
	

	// 内存映射
	lcd->map = mmap( NULL , LCD_SIZE , PROT_READ | 
						PROT_WRITE , MAP_SHARED ,
						lcd->fd , 0 );
	if (lcd->map == MAP_FAILED)
	{
		perror( "mmap error " );
		goto MMAPError ; // 无条件跳转到指定的位置执行
	}

	lcd->lcdSize = LCD_SIZE ;
	

	// 返回
	return lcd ;

MMAPError:
	close (lcd->fd);
OpenLcdError:
	free(lcd) ;
	return NULL ;
}


int ShowBmp( lcdInfo * lcd , const char * FilePath , int x , int y )
{

	// 打开图像文件
	FILE * fp = fopen( FilePath  , "r");
	if (fp == NULL)
	{
		perror("open file error");
		return -1 ;
	}

	// 读取图像的头部信息（文件头+信息头）
	// 读取文件信息头数据
	BITMAPFILEHEADER fileInfo = {0};
	int retVla = fread(  &fileInfo , 1 ,sizeof(fileInfo) , fp );
	printf("retVal:%d\n", retVla );

	printf("文件大小：%d\n" , fileInfo.bfSize);
	printf("RGB偏移位置: %d\n" , fileInfo.bfOffBits );


	// 读取图像信息头数据
	BITMAPINFOHEADER PicInfo = { 0 } ; 
	retVla = fread(  &PicInfo , 1 ,sizeof(PicInfo) , fp );
	printf("retVal:%d\n", retVla );

	printf("图像宽高[%d,%d]\n" , PicInfo.biWidth , PicInfo.biHeight );
	printf("图像色深[%d]\n" , PicInfo.biBitCount );
	printf("压缩模式[%d]\n" , PicInfo.biCompression );

	// 计算并检测是否存在行尾空白符（为了能被4整除）
	int Whitespace = 0 ;

	if( PicInfo.biWidth * 3 % 4 )
	{
		// 计算的到为了能4整除而补充的空白符数量
		Whitespace = 4 - PicInfo.biWidth * 3 % 4 ;
	}

	// 读取图像的BGR颜色值
	char Bgr [ PicInfo.biHeight * PicInfo.biWidth * 3 +  PicInfo.biHeight * Whitespace ];
	retVla = fread( Bgr , 1 , sizeof(Bgr) , fp );
	printf("读取到图像RGB:%d\n" , retVla );



	// 关闭图像文件
	fclose(fp) ;

	// 把BGR转换为ARGB
	int ARGB [PicInfo.biHeight] [PicInfo.biWidth] ;
	for (int y = 0; y < PicInfo.biHeight ; y++)
	{
		for (int x = 0; x < PicInfo.biWidth ; x++)
		{
			ARGB[PicInfo.biHeight-y-1][x] = 	Bgr[(x+y*PicInfo.biWidth)*3+0 + y*Whitespace] << 0 | 
												Bgr[(x+y*PicInfo.biWidth)*3+1 + y*Whitespace] << 8 | 
												Bgr[(x+y*PicInfo.biWidth)*3+2 + y*Whitespace]<< 16 ;
		}
		
	}

	// 把转换后的ARGB显示到屏幕中
	for (int Tmp_y = 0; Tmp_y < PicInfo.biHeight ; Tmp_y++)
	{
		for (int Tmp_x = 0; Tmp_x < PicInfo.biWidth ; Tmp_x++)
		{
			// map = ARGB ;
			if ((Tmp_x + x) < LCD_WIDTH && (Tmp_y+y) < LCD_HEIGHT )
			{
				*( lcd->map +Tmp_x+x+((Tmp_y+y)*LCD_WIDTH)) 
										= ARGB[Tmp_y][Tmp_x] ;
			}
		}
	}

	// 返回
	return 0 ;

}